//!Includes

#include "Segmentation.h"

//!Global Functions


namespace algorithms
{

/**
 * class Segmentation
 *
 *
 * Autor:David Bevilaqua
 *
 *
 * DESCRIPTION:
 *
 */

//!Constructors/Destructors

/**
 * Empty Constructor
 */
Segmentation::Segmentation ( )
{

}

/**
 * Empty Destructor
 */
Segmentation::~Segmentation ( )
{

}

//!Public Accessor Methods
//

void Segmentation::SetSourceImage(IplImage *SourceImage)
{
	m_pSourceImage=SourceImage;
}

void Segmentation::SetDestinImage(IplImage *DestinImage)
{
	m_pDestinImage=DestinImage;
}

IplImage * Segmentation::GetDestinImage( )
{
	return m_pDestinImage;
}

IplImage * Segmentation::GetSourceImage( )
{
	return m_pSourceImage;
}

void Segmentation::SetTarget(CvBox2D *pBox)
{
m_pBox=pBox;
}

CvBox2D  Segmentation::GetTarget( )
{
return *m_pBox;
}

std::vector <CvPoint>  Segmentation::GetTargetPoints( )
{
return m_TargetPoints;
}
//!Public Methods

void Segmentation::ClearTargetPoints( )
{
m_TargetPoints.clear();
}

bool Segmentation::FindTarget( )
{
	int HueHigh=80,HueLow=40,ValHigh=255,ValLow=20,SatHigh=255,SatLow=20;
	CvMemStorage* storage = cvCreateMemStorage(0);
	CvSeq* Contour = NULL;
	CvSeq* ContourTemp = NULL;
	int i,j;
	IplImage* hsv = cvCreateImage( cvGetSize(m_pSourceImage), IPL_DEPTH_8U, 3 );
	cvCvtColor( m_pSourceImage, hsv, CV_BGR2HSV );
	int area;
	CvPoint2D32f center;
	float radius=0;
	m_nContours=0;
	IplImage* h_plane = cvCreateImage( cvGetSize( m_pSourceImage ), 8, 1 );
	IplImage* s_plane = cvCreateImage( cvGetSize( m_pSourceImage ), 8, 1 );
	IplImage* v_plane = cvCreateImage( cvGetSize( m_pSourceImage ), 8, 1 );
	m_pDestinImage = cvCreateImage( cvGetSize( m_pSourceImage ), 8, 1 );
	cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 );

	uchar* pHue=(uchar*)h_plane->imageData;
	uchar* pVal=(uchar*)s_plane->imageData;
	uchar* pSat=(uchar*)v_plane->imageData;
	uchar* pResult=(uchar*)m_pDestinImage->imageData;
	for(j=0;h_plane->height>j;j++)
	{
		for(i=0;h_plane->width>i;i++)
		{
			if(filterHue&&filterVal&&filterSat)
			{
				pResult[i+j*h_plane->widthStep]=255;
			}
			else
			{
				pResult[i+j*h_plane->widthStep]=0;
			}
		}
	}

	cvErode(m_pDestinImage,m_pDestinImage,NULL,1);
	cvDilate(m_pDestinImage,m_pDestinImage,NULL,1);

	cvCanny(m_pDestinImage,m_pDestinImage,200,250);

	cvDilate(m_pDestinImage,m_pDestinImage,NULL,2);

	int nct=cvFindContours( m_pDestinImage, storage, &Contour,sizeof(CvContour),CV_RETR_TREE);
	cvZero( m_pDestinImage);
	ContourTemp=Contour;

	if( Contour)
	{
		for(i=0;Contour!=NULL;i++)
		{
			int x=0,y=0,flag=0;
			m_BoxTemp=cvMinAreaRect2(Contour,NULL);
			area=cvContourArea(Contour,CV_WHOLE_SEQ);
			cvMinEnclosingCircle(Contour,&center,&radius);

			for( int j=0; j<Contour->total; ++j ) {
				CvPoint* p = (CvPoint*)cvGetSeqElem ( Contour, j );
				x=p->x;
				y=p->y;

				if(std::sqrt(std::pow(x-m_BoxTemp.center.x,2)+std::pow(m_BoxTemp.center.y-y,2))<m_BoxTemp.size.width*0.4)
				{
				flag=1;
				}

			}
			if(area<-1000&&flag==0)
			{
				m_nContours++;
				*m_pBox=m_BoxTemp;
				cvDrawContours(m_pDestinImage,Contour,cvScalarAll(255),cvScalarAll(255),-1,CV_FILLED);
			}
			Contour=Contour->h_next;
		}
	}
	if(m_nContours==1)
	{
		Contour=ContourTemp;
		cvReleaseImage(&hsv);
		cvReleaseImage(&h_plane);
		cvReleaseImage(&s_plane);
		cvReleaseImage(&v_plane);
		cvReleaseMemStorage(&storage);
		cvClearSeq(Contour);
		return true;
	}
	else if(nct!=0)
	{
		Contour=ContourTemp;
		cvReleaseImage(&hsv);
		cvReleaseImage(&h_plane);
		cvReleaseImage(&s_plane);
		cvReleaseImage(&v_plane);
		cvReleaseMemStorage(&storage);
		cvClearSeq(Contour);
		return false;
	}
	else
	{
		Contour=ContourTemp;
		cvReleaseImage(&hsv);
		cvReleaseImage(&h_plane);
		cvReleaseImage(&s_plane);
		cvReleaseImage(&v_plane);
		cvReleaseMemStorage(&storage);

		return false;
	}


	cvReleaseImage(&hsv);
	cvReleaseImage(&h_plane);
	cvReleaseImage(&s_plane);
	cvReleaseImage(&v_plane);
	cvReleaseMemStorage(&storage);
	return false;

}

bool Segmentation::FindTargetPoints( )
{

	int HueHigh=140,HueLow=100,ValHigh=255,ValLow=0,SatHigh=255,SatLow=0;
	CvMemStorage* storage = cvCreateMemStorage(0);
	CvSeq* Contour = NULL;
	CvSeq* ContourTemp = NULL;
	int i,j;
	IplImage* hsv = cvCreateImage( cvGetSize(m_pSourceImage), IPL_DEPTH_8U, 3 );
	cvCvtColor( m_pSourceImage, hsv, CV_BGR2HSV );
	CvPoint2D32f center;
	float radius=0;
	m_nContours=0;

	IplImage* h_plane = cvCreateImage( cvGetSize( m_pSourceImage ), 8, 1 );
	IplImage* s_plane = cvCreateImage( cvGetSize( m_pSourceImage ), 8, 1 );
	IplImage* v_plane = cvCreateImage( cvGetSize( m_pSourceImage ), 8, 1 );
	m_pDestinImage = cvCreateImage( cvGetSize( m_pSourceImage ), 8, 1 );
	cvCvtPixToPlane( hsv, h_plane, s_plane, v_plane, 0 );

	uchar* pHue=(uchar*)h_plane->imageData;
	uchar* pVal=(uchar*)s_plane->imageData;
	uchar* pSat=(uchar*)v_plane->imageData;
	uchar* pResult=(uchar*)m_pDestinImage->imageData;
	for(j=0;h_plane->height>j;j++)
	{
		for(i=0;h_plane->width>i;i++)
		{
			if(filterHue&&filterVal&&filterSat)
			{
				pResult[i+j*h_plane->widthStep]=255;
			}
			else
			{
				pResult[i+j*h_plane->widthStep]=0;
			}
		}
	}

	cvErode(m_pDestinImage,m_pDestinImage,NULL,1);
	cvDilate(m_pDestinImage,m_pDestinImage,NULL,1);

	cvCanny(m_pDestinImage,m_pDestinImage,100,150);

	cvDilate(m_pDestinImage,m_pDestinImage,NULL,1);

	int nct=cvFindContours( m_pDestinImage, storage, &Contour,sizeof(CvContour),CV_RETR_TREE);
	cvZero( m_pDestinImage);
	ContourTemp=Contour;

	if( Contour)
	{
		for(i=0;Contour!=NULL;i++)
		{
			cvMinEnclosingCircle(Contour,&center,&radius);
			if(radius>m_pSourceImage->height*0.05&&radius<m_pSourceImage->height*0.2&&center.x>m_pSourceImage->width*0.1&&center.x<m_pSourceImage->width*0.9&&center.y>m_pSourceImage->height*0.1&&center.y<m_pSourceImage->height*0.9)
			{
				m_nContours++;
				m_TargetPoints.push_back(cvPoint(center.x,center.y));
				cvDrawContours(m_pDestinImage,Contour,cvScalarAll(255),cvScalarAll(255),-1,CV_FILLED);
			}
			Contour=Contour->h_next;
		}
	}
	if(m_nContours==5)
	{
		Contour=ContourTemp;
		cvReleaseImage(&hsv);
		cvReleaseImage(&h_plane);
		cvReleaseImage(&s_plane);
		cvReleaseImage(&v_plane);
		cvReleaseMemStorage(&storage);
		return true;
	}
	else if(m_nContours>0)
	{
		Contour=ContourTemp;
		cvReleaseImage(&hsv);
		cvReleaseImage(&h_plane);
		cvReleaseImage(&s_plane);
		cvReleaseImage(&v_plane);
		cvReleaseMemStorage(&storage);
		m_TargetPoints.clear();
		return false;
	}
	else if(nct!=0)
	{
		Contour=ContourTemp;
		cvReleaseImage(&hsv);
		cvReleaseImage(&h_plane);
		cvReleaseImage(&s_plane);
		cvReleaseImage(&v_plane);
		cvReleaseMemStorage(&storage);
		return false;
	}
	else{
		Contour=ContourTemp;
		cvReleaseImage(&hsv);
		cvReleaseImage(&h_plane);
		cvReleaseImage(&s_plane);
		cvReleaseImage(&v_plane);
		cvReleaseMemStorage(&storage);
		return false;
	}
}


//!Protected Methods

//!Private Methods


/**
 * Starts all the attributes of
 * the Segmentation
 */



}
